Õppige selgeks Reacti useFormState hook. Põhjalik juhend sujuvaks vormi olekuhalduseks, serveripoolseks valideerimiseks ja paremaks kasutajakogemuseks Server Actions'i abil.
React useFormState: SĂĽvaĂĽlevaade kaasaegsest vormihaldusest ja valideerimisest
Vormid on veebis interaktiivsuse nurgakivi. Alates lihtsatest kontaktivormidest kuni keerukate mitmeastmeliste viisarditeni on need kasutaja sisendi ja andmete edastamise jaoks hädavajalikud. Aastaid on Reacti arendajad navigeerinud olekuhalduse lahenduste maastikul, mis ulatub lihtsatest useState hookidest põhiliste stsenaariumide jaoks kuni võimsate kolmandate osapoolte teekideni nagu Formik ja React Hook Form keerukamate vajaduste jaoks. Kuigi need tööriistad on suurepärased, areneb React pidevalt, et pakkuda integreeritumaid ja võimsamaid primitiive.
Siin tulebki mängu useFormState, React 18-s tutvustatud hook. Algselt loodud sujuvaks töötamiseks React Server Actions'iga, pakub useFormState sujuvamat, robustsemat ja natiivset lähenemist vormi oleku haldamisele, eriti kui tegemist on serveripoolse loogika ja valideerimisega. See lihtsustab serverist tuleva tagasiside, näiteks valideerimisvigade või eduteadete, kuvamist otse teie kasutajaliideses.
See põhjalik juhend viib teid sügavale useFormState hooki maailma. Uurime selle põhikontseptsioone, praktilisi rakendusi, täiustatud mustreid ja seda, kuidas see sobitub kaasaegse Reacti arenduse laiemasse ökosüsteemi. Olenemata sellest, kas arendate rakendusi Next.js-i, Remixi või puhta Reactiga, annab useFormState'i mõistmine teile võimsa tööriista paremate ja vastupidavamate vormide loomiseks.
Mis on `useFormState` ja miks me seda vajame?
Oma olemuselt on useFormState hook, mis on loodud oleku värskendamiseks vormi tegevuse tulemuse põhjal. Mõelge sellest kui useReducer'i spetsialiseeritud versioonist, mis on kohandatud spetsiaalselt vormide esitamiseks. See ületab elegantselt lõhe kliendipoolse kasutaja interaktsiooni ja serveripoolse töötlemise vahel.
Enne useFormState'i võis tüüpiline serverit kaasav vormi esitamise voog välja näha selline:
- Kasutaja täidab vormi.
- Kliendipoolne olek (nt kasutades
useState) jälgib sisendväärtusi. - Esitamisel takistab sündmusekäsitleja (
onSubmit) brauseri vaikekäitumist. fetch-päring koostatakse käsitsi ja saadetakse serveri API otspunkti.- Hallatakse laadimise olekuid (nt
const [isLoading, setIsLoading] = useState(false)). - Server töötleb päringu, teostab valideerimise ja suhtleb andmebaasiga.
- Server saadab tagasi JSON-vastuse (nt
{ success: false, errors: { email: 'Invalid format' } }). - Kliendipoolne kood parssib selle vastuse ja värskendab teist olekumuutujat, et kuvada vigu või eduteateid.
See protsess, kuigi toimiv, sisaldab märkimisväärset korduvkoodi laadimise olekute, veaolekute ja päringu/vastuse tsükli haldamiseks. useFormState, eriti kui see on ühendatud Server Actions'iga, lihtsustab seda dramaatiliselt, luues deklaratiivsema ja integreerituma voo.
useFormState'i kasutamise peamised eelised on:
- Sujuv serveri integratsioon: See on natiivne lahendus Server Actions'i vastuste käsitlemiseks, muutes serveripoolse valideerimise teie komponendis esmaklassiliseks kodanikuks.
- Lihtsustatud olekuhaldus: See tsentraliseerib vormi oleku uuenduste loogika, vähendades vajadust mitme
useStatehooki järele andmete, vigade ja esitamise oleku jaoks. - Progressiivne täiustamine: Vormid, mis on ehitatud
useFormState'i ja Server Actions'iga, võivad töötada isegi siis, kui JavaScript on kliendis keelatud, kuna need on ehitatud standardsete HTML-vormide esitamise vundamendile. - Parem kasutajakogemus: See muudab lihtsamaks kasutajale vahetu ja kontekstipõhise tagasiside andmise, näiteks tekstisisesed valideerimisvead või eduteated, otse pärast vormi esitamist.
useFormState hooki signatuuri mõistmine
Hooki valdamiseks vaatame kõigepealt selle signatuuri ja tagastusväärtusi. See on lihtsam, kui esmapilgul võib tunduda.
const [state, formAction] = useFormState(action, initialState);
Parameetrid:
action: See on funktsioon, mis käivitatakse vormi esitamisel. See funktsioon saab kaks argumenti: vormi eelnev olek ja esitatud vormi andmed. See peab tagastama uue oleku. Tavaliselt on see Server Action, kuid see võib olla mis tahes funktsioon.initialState: See on väärtus, mida soovite vormi olekul algselt, enne mis tahes esitamist, omada. See võib olla mis tahes serialiseeritav väärtus (string, number, objekt jne).
Tagastusväärtused:
useFormState tagastab massiivi täpselt kahe elemendiga:
state: Vormi praegune olek. Esmasel renderdamisel on see teie poolt antudinitialState. Pärast vormi esitamist on see väärtus, mille teieaction-funktsioon tagastas. Seda olekut kasutate kasutajaliidese tagasiside, näiteks veateadete, renderdamiseks.formAction: Uus tegevusfunktsioon, mille edastate oma<form>elemendiaction-atribuudile. Kui see tegevus käivitatakse (vormi esitamisega), kutsub React välja teie algseaction-funktsiooni eelmise oleku ja vormi andmetega ning värskendab seejärelstate'i tulemusega.
See muster võib tunduda tuttav, kui olete kasutanud useReducer'it. action-funktsioon on nagu reducer, initialState on algolek ja React tegeleb teie eest saatmisega, kui vorm esitatakse.
Praktiline esimene näide: lihtne tellimisvorm
Loome lihtsa uudiskirja tellimisvormi, et näha useFormState'i tegevuses. Meil on üks e-posti sisend ja esitamisnupp. Serveri tegevus teostab põhilise valideerimise, et kontrollida, kas e-post on antud ja kas see on kehtivas vormingus.
Esmalt defineerime oma serveri tegevuse. Kui kasutate Next.js-i, saate selle paigutada samasse faili oma komponendiga, lisades funktsiooni ĂĽlaossa direktiivi 'use server';.
// actions.js-is või teie komponendi faili ülaosas direktiiviga 'use server'
export async function subscribe(previousState, formData) {
const email = formData.get('email');
if (!email) {
return { message: 'E-posti aadress on kohustuslik.' };
}
// Lihtne regex demonstreerimise eesmärgil
if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(email)) {
return { message: 'Palun sisestage kehtiv e-posti aadress.' };
}
// Siin salvestaksite tavaliselt e-posti andmebaasi
console.log(`Subscribing with email: ${email}`);
// Simuleerime viivitust
await new Promise(res => setTimeout(res, 1000));
return { message: 'Täname tellimuse eest!' };
}
NĂĽĂĽd loome kliendikomponendi, mis kasutab seda tegevust koos useFormState'iga.
'use client';
import { useFormState } from 'react-dom';
import { subscribe } from './actions';
const initialState = {
message: null,
};
export function SubscriptionForm() {
const [state, formAction] = useFormState(subscribe, initialState);
return (
<form action={formAction}>
<h3>Telli meie uudiskiri</h3>
<div>
<label htmlFor="email">E-posti aadress</label>
<input type="email" id="email" name="email" required />
</div>
<button type="submit">Telli</button>
{state?.message && <p>{state.message}</p>}
</form>
);
}
Vaatame lähemalt, mis toimub:
- Impordime
useFormStatepaketistreact-dom(märkus: mittereact). - Defineerime
initialStateobjekti. See tagab, et meiestatemuutujal on ühtlane kuju alates esimesest renderdamisest. - Kutsume välja
useFormState(subscribe, initialState). See seob meie komponendi olekusubscribeserveri tegevusega. - Tagastatud
formActionedastatakse<form>elemendiactionatribuudile. See on maagiline ühendus. - Renderdame tingimuslikult sõnumi meie
stateobjektist. Esimesel renderdamisel onstate.messageväärtusnull, seega midagi ei kuvata. - Kui kasutaja vormi esitab, käivitab React
formAction'i. See kutsub esile meiesubscribeserveri tegevuse.subscribefunktsioon saabpreviousState(algselt meieinitialState) jaformData. - Serveri tegevus käivitab oma loogika ja tagastab uue olekuobjekti (nt
{ message: 'E-posti aadress on kohustuslik.' }). - React võtab selle uue oleku vastu ja renderdab
SubscriptionFormkomponendi uuesti.statemuutuja hoiab nüüd uut objekti ja meie tingimuslik lõik kuvab vea- või eduteate.
See on uskumatult võimas. Oleme rakendanud täieliku klient-server valideerimistsükli minimaalse kliendipoolse olekuhalduse korduvkoodiga.
Kasutajakogemuse parandamine `useFormStatus`'iga
Meie vorm töötab, kuid kasutajakogemus võiks olla parem. Kui kasutaja klõpsab "Telli", jääb nupp aktiivseks ja puudub visuaalne viide, et midagi toimub, kuni server vastab. Siin tulebki mängu useFormStatus hook.
useFormStatus hook annab olekuteavet viimase vormi esitamise kohta. Oluline on, et seda tuleb kasutada komponendis, mis on <form> elemendi laps. See ei tööta, kui seda kutsutakse samas komponendis, mis renderdab vormi.
Loome eraldi SubmitButton komponendi.
'use client';
import { useFormStatus } from 'react-dom';
export function SubmitButton() {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? 'Tellin...' : 'Telli'}
</button>
);
}
NĂĽĂĽd saame oma SubscriptionForm'i uuendada, et kasutada seda uut komponenti:
// ... impordid
import { SubmitButton } from './SubmitButton';
// ... initialState ja muu kood
export function SubscriptionForm() {
const [state, formAction] = useFormState(subscribe, initialState);
return (
<form action={formAction}>
{/* ... vormi sisendid ... */}
<SubmitButton /> {/* Asenda vana nupp */}
{state?.message && <p>{state.message}</p>}
</form>
);
}
Selle muudatusega muutub vormi esitamisel useFormStatus'ist saadav pending väärtus true'ks. Meie SubmitButton komponent renderdatakse uuesti, keelates nupu ja muutes selle teksti "Tellin...". Kui serveri tegevus on lõpule jõudnud ja useFormState oleku värskendanud, ei ole vorm enam ootel ja nupp naaseb oma algsesse olekusse. See annab kasutajale olulist tagasisidet ja hoiab ära topeltesitamised.
Täiustatud valideerimine struktureeritud veaolekute ja Zod'iga
Üksik sõnumistring sobib lihtsate vormide jaoks, kuid pärismaailma rakendused nõuavad sageli väljapõhiseid valideerimisvigu. Saame selle hõlpsasti saavutada, tagastades oma serveri tegevusest struktureerituma olekuobjekti.
Täiustame oma tegevust, et see tagastaks objekti errors võtmega, mis omakorda sisaldab sõnumeid konkreetsete väljade jaoks. See on ka ideaalne võimalus tutvustada skeemi valideerimise teeki nagu Zod robustsema ja hooldatavama valideerimisloogika jaoks.
1. samm: installi Zod
npm install zod
2. samm: uuenda serveri tegevust
Loome Zod skeemi, et määratleda meie vormiandmete oodatav kuju ja valideerimisreeglid. Seejärel kasutame sissetuleva formData valideerimiseks schema.safeParse().
'use server';
import { z } from 'zod';
// Defineerime meie vormi skeemi
const contactSchema = z.object({
name: z.string().min(2, { message: 'Nimi peab olema vähemalt 2 tähemärki pikk.' }),
email: z.string().email({ message: 'Vigane e-posti aadress.' }),
message: z.string().min(10, { message: 'Sõnum peab olema vähemalt 10 tähemärki pikk.' }),
});
export async function submitContactForm(previousState, formData) {
const validatedFields = contactSchema.safeParse({
name: formData.get('name'),
email: formData.get('email'),
message: formData.get('message'),
});
// Kui valideerimine ebaõnnestub, tagasta vead
if (!validatedFields.success) {
return {
errors: validatedFields.error.flatten().fieldErrors,
message: 'Valideerimine ebaõnnestus. Palun kontrollige oma sisendeid.',
};
}
// Kui valideerimine õnnestub, töötle andmeid
// Näiteks saada e-kiri või salvesta andmebaasi
console.log('Success!', validatedFields.data);
// ... töötlemise loogika ...
// Tagasta edukas olek
return {
errors: {},
message: 'Täname teid sõnumi eest! Võtame teiega peagi ühendust.',
};
}
Pange tähele, kuidas me kasutame validatedFields.error.flatten().fieldErrors. See on käepärane Zodi utiliit, mis teisendab veaobjekti kasutajasõbralikumaks struktuuriks, näiteks: { name: ['Nimi peab olema vähemalt 2 tähemärki pikk.'], message: ['Sõnum on liiga lühike'] }.
3. samm: uuenda kliendikomponenti
Nüüd uuendame oma vormikomponenti, et see käsitleks seda struktureeritud veaolekut.
'use client';
import { useFormState } from 'react-dom';
import { submitContactForm } from './actions';
import { SubmitButton } from './SubmitButton'; // Eeldades, et meil on esitamisnupp
const initialState = {
message: null,
errors: {},
};
export function ContactForm() {
const [state, formAction] = useFormState(submitContactForm, initialState);
return (
<form action={formAction}>
<h2>Võta meiega ühendust</h2>
<div>
<label htmlFor="name">Nimi</label>
<input type="text" id="name" name="name" />
{state.errors?.name && (
<p className="error">{state.errors.name[0]}</p>
)}
</div>
<div>
<label htmlFor="email">E-post</label>
<input type="email" id="email" name="email" />
{state.errors?.email && (
<p className="error">{state.errors.email[0]}</p>
)}
</div>
<div>
<label htmlFor="message">Sõnum</label>
<textarea id="message" name="message" />
{state.errors?.message && (
<p className="error">{state.errors.message[0]}</p>
)}
</div>
<SubmitButton />
{state.message && <p className="form-status">{state.message}</p>}
</form>
);
}
See muster on uskumatult skaleeritav ja robustne. Teie serveri tegevusest saab valideerimisloogika ainus tõeallikas ja Zod pakub deklaratiivset ja tüübikindlat viisi nende reeglite määratlemiseks. Kliendikomponent muutub lihtsalt useFormState'i pakutava oleku tarbijaks, kuvades vigu seal, kus need kuuluvad. Selline ülesannete eraldamine muudab koodi puhtamaks, lihtsamini testitavaks ja turvalisemaks, kuna valideerimine on alati serveris jõustatud.
`useFormState` vs. teised vormihalduslahendused
Uue tööriistaga tekib küsimus: "Millal peaksin seda kasutama selle asemel, mida ma juba tean?" Võrdleme useFormState'i teiste levinud lähenemisviisidega.
`useFormState` vs. `useState`
- `useState` on ideaalne lihtsate, ainult kliendipoolsete vormide jaoks või kui peate enne esitamist teostama keerukaid, reaalajas toimuvaid kliendipoolseid interaktsioone (näiteks reaalajas valideerimine kasutaja sisestamise ajal). See annab teile otsese ja detailse kontrolli.
- `useFormState` on parim siis, kui vormi olek sõltub peamiselt serveri vastusest. See on loodud vormi esitamise päringu/vastuse tsükli jaoks ja on eelistatud valik Server Actions'i kasutamisel. See eemaldab vajaduse käsitsi hallata fetch-kutseid, laadimise olekuid ja vastuse parssimist.
`useFormState` vs. kolmandate osapoolte teegid (React Hook Form, Formik)
Teegid nagu React Hook Form ja Formik on küpsed, funktsioonirikkad lahendused, mis pakuvad laiaulatuslikku tööriistakomplekti vormihalduseks. Nad pakuvad:
- Täiustatud kliendipoolset valideerimist (sageli skeemi integreerimisega Zod, Yup jms jaoks).
- Keerukat olekuhaldust pesastatud väljade, väljade massiivide ja muu jaoks.
- Jõudluse optimeerimist (nt renderdamiste isoleerimine ainult muutuvatele sisenditele).
- Abilisi kontrollerkomponentidele ja integreerimiseks kasutajaliidese teekidega.
Niisiis, millal valida kumb?
- Valige
useFormState, kui:- Kasutate React Server Actions'it ja soovite natiivset, integreeritud lahendust.
- Teie peamine valideerimise tõeallikas on server.
- Hindate progressiivset täiustamist ja soovite, et teie vormid töötaksid ka ilma JavaScriptita.
- Teie vormiloogika on suhteliselt lihtne ja keskendub esitamise/vastuse tsĂĽklile.
- Valige kolmanda osapoole teek, kui:
- Vajate ulatuslikku ja keerukat kliendipoolset valideerimist kohese tagasisidega (nt valideerimine on blur või on change sündmustel).
- Teil on väga dünaamilised vormid (nt väljade lisamine/eemaldamine, tingimuslik loogika).
- Te ei kasuta raamistikku, millel on Server Actions, ja ehitate oma klient-server suhtluskihi REST või GraphQL API-dega.
- Vajate peeneteralist kontrolli jõudluse ja uuesti renderdamiste üle väga suurtes vormides.
Samuti on oluline märkida, et need ei välista teineteist. Saate kasutada React Hook Formi oma vormi kliendipoolse oleku ja valideerimise haldamiseks ning seejärel kasutada selle esitamise käsitlejat Server Action'i kutsumiseks. Kuid paljude levinud kasutusjuhtude puhul pakub useFormState'i ja Server Actions'i kombinatsioon lihtsamat ja elegantsemat lahendust.
Parimad praktikad ja levinud lõksud
Et useFormState'ist maksimumi võtta, arvestage järgmiste parimate tavadega:
- Hoidke tegevused fookuses: Teie vormi tegevusfunktsioon peaks vastutama ühe asja eest: vormi esitamise töötlemise eest. See hõlmab valideerimist, andmete muutmist (andmebaasi salvestamist) ja uue oleku tagastamist. Vältige kõrvalmõjusid, mis ei ole seotud vormi tulemusega.
- Määratlege ühtlane oleku kuju: Alustage alati hästi määratletud
initialState'iga ja veenduge, et teie tegevus tagastab alati sama kujuga objekti, isegi edu korral. See hoiab ära käitusaegsed vead kliendis, kui proovitakse pääseda juurde omadustele nagustate.errors. - Võtke omaks progressiivne täiustamine: Pidage meeles, et Server Actions töötab ka ilma kliendipoolse JavaScriptita. Kujundage oma kasutajaliides nii, et see käsitleks mõlemat stsenaariumi sujuvalt. Näiteks veenduge, et serveris renderdatud valideerimissõnumid oleksid selged, kuna kasutajal pole ilma JS-ita keelatud nupu oleku eelist.
- Eraldage kasutajaliidese mured: Kasutage komponente nagu meie
SubmitButton, et kapseldada olekust sõltuvat kasutajaliidest. See hoiab teie peamise vormikomponendi puhtamana ja austab reeglit, etuseFormStatus'i tuleb kasutada lapsikomponendis. - Ärge unustage ligipääsetavust: Vigade kuvamisel kasutage oma sisendväljadel ARIA atribuute nagu
aria-invalidja seostage veateated nende vastavate sisenditega, kasutadesaria-describedby, et tagada teie vormide ligipääsetavus ekraanilugeja kasutajatele.
Levinud lõks: useFormStatus'i kasutamine samas komponendis
Sage viga on useFormStatus'i kutsumine samas komponendis, mis renderdab <form>-märgendit. See ei tööta, sest hook peab olema vormi kontekstis, et pääseda ligi selle olekule. Eraldage alati see osa oma kasutajaliidesest, mis vajab olekut (näiteks nupp), omaette lapsikomponenti.
Kokkuvõte
useFormState hook, koos Server Actions'iga, kujutab endast olulist arengut selles, kuidas me Reactis vorme käsitleme. See suunab arendajaid robustsema, serverikeskse valideerimismudeli poole, lihtsustades samal ajal kliendipoolset olekuhaldust. Abstraheerides esitamise elutsükli keerukused, võimaldab see meil keskenduda kõige olulisemale: oma äriloogika määratlemisele ja sujuva kasutajakogemuse loomisele.
Kuigi see ei pruugi asendada laiaulatuslikke kolmandate osapoolte teeke igal kasutusjuhul, pakub useFormState võimsa, natiivse ja progressiivselt täiustatud vundamendi enamiku vormide jaoks kaasaegsetes veebirakendustes. Selle mustrite valdamise ja selle koha mõistmisega Reacti ökosüsteemis saate luua vastupidavamaid, hooldatavamaid ja kasutajasõbralikumaid vorme vähema koodi ja suurema selgusega.